package ichubmetadata

import (
	"database/sql"
	"gitee.com/ichub/webcli/common/base/basedto"
	"gitee.com/ichub/webcli/common/base/baseutils"
	"gitee.com/ichub/webcli/common/base/baseutils/stringutils"
	"github.com/sirupsen/logrus"
	"strings"
	"time"
)

/*
@Title    文件名称: ichubrecords.go
@Description  描述: 元数据--记录

@Author  作者: leijianming@163.com  时间(2024-02-21 22:38:21)
@Update  作者: leijianming@163.com  时间(2024-02-21 22:38:21)
*/
const DefaultTable = "rules"

var DefaultFields = []string{
	"*",
}

type IchubRecords struct {
	basedto.BaseEntity

	TableName string   `json:"table_name"`
	Fields    []string `json:"fields"`

	Rows    [][]*IchubField          `json:"-"`
	Records []map[string]interface{} `json:"records"`
	Count   int                      `json:"count"`

	TimeToInt bool `json:"time_to_int"`
}

func NewIchubRecords() *IchubRecords {
	var this = &IchubRecords{
		TableName: DefaultTable,
		TimeToInt: true,
		Records:   []map[string]interface{}{},
		Fields:    DefaultFields}
	this.InitProxy(this)
	return this
}
func (this *IchubRecords) TableFields(tableName, fields string) *IchubRecords {
	this.TableName = tableName
	this.Fields = strings.Split(fields, ",")
	return this
}

func (this *IchubRecords) Append(row []*IchubField) {
	this.Rows = append(this.Rows, row)

}

func (this *IchubRecords) MakeIchubFields() []*IchubField {
	var IchubFields = []*IchubField{}

	for _, field := range this.Fields {
		var ichubField = MakeIchubField(this.TableName, field)
		IchubFields = append(IchubFields, ichubField)
	}
	return IchubFields
}

func (this *IchubRecords) NewIchubFields2Result() ([]interface{}, []*IchubField) {
	var ichubFields = this.MakeIchubFields()
	var result = []interface{}{}
	for _, v := range ichubFields {
		result = append(result, &v.Value)
	}
	return result, ichubFields
}

func (this *IchubRecords) CheckType(field *IchubField) string {
	var i = field.Value

	switch i.(type) {
	case *string:
		return "*string"
	case *bool:
		return "*bool"
	case *int:
		return "*int"
	case *int8:
		return "*int8"
	case *int16:
		return "*int16"
	case *int32:
		return "*int32"
	case *int64:
		return "*int64"
	case *byte:
		return "*byte"
	case *time.Time:
		return "*time.Time"

	case *[]uint8:
		return "*[]uint8"

	case *uint16:
		return "*uint16"
	case *uint32:
		return "*uint32"
	case *uint64:
		return "*uint64"
	case *float32:
		return "*float32"
	case *float64:
		return "*float64"

	case bool:
		return "bool"
	case int:
		return "int"
	case []uint8:
		return "[]uint8"
	case int8:
		return "int8"
	case int16:
		return "int16"
	case int32:
		return "int32"
	case int64:
		return "int64"
	case uint8:
		return "uint8"
	case uint16:
		return "uint16"
	case uint32:
		return "uint32"
	case uint64:
		return "uint64"
	case float32:
		return "float32"
	case float64:
		return "float64"

	case time.Time:
		return "time.Time"
	case string:
		return "string"
	}

	return field.GoType
}

func (this *IchubRecords) PtrField2Value(field *IchubField) interface{} {

	var ptr = field.Value
	var checkType = this.CheckType(field)

	if checkType == "*int" {
		if ptr == nil {
			return new(int)
		}
		return ptr.(*int)
	}
	if checkType == "*bool" {
		if ptr == nil {
			return new(bool)
		}
		return ptr.(*bool)
	}
	if checkType == "*uint8" {
		if ptr == nil {
			return new(uint8)
		}
		return ptr.(*uint8)
	}
	if checkType == "*[]uint8" {
		if ptr == nil {
			return new(string)
		}
		var s = baseutils.Any2Str(ptr)
		return &s
	}
	if checkType == "*int8" {
		if ptr == nil {
			return new(int8)
		}
		return ptr.(*int8)
	}
	if checkType == "*int16" {
		if ptr == nil {
			return new(int16)
		}
		return ptr.(*int16)
	}
	if checkType == "*int32" {
		if ptr == nil {
			return new(int32)
		}
		return ptr.(*int32)
	}
	if checkType == "*uint32" {
		if ptr == nil {
			return new(uint32)
		}

		return ptr.(*uint32)
	}
	if checkType == "*uint64" {
		if ptr == nil {
			return uint64(0)
		}
		return ptr.(*uint64)
	}
	if checkType == "*int64" {
		if ptr == nil {
			return new(int64)
		}
		return ptr.(*int64)
	}
	if checkType == "*float32" {
		if ptr == nil {
			return new(float32)
		}
		return ptr.(*float32)
	}
	if checkType == "*float64" {
		if ptr == nil {
			return new(float64)
		}
		return ptr.(*float64)
	}
	if checkType == "*string" {
		if ptr == nil {
			return new(string)
		}
		return ptr.(*string)
	}

	if checkType == "*time.Time" {
		return this.PtrTimeField2Value(field)

	}

	//////
	if checkType == "int" {
		if ptr == nil {
			return 0
		}
		return ptr.(int)
	}
	if checkType == "bool" {
		if ptr == nil {
			return false
		}
		return ptr.(bool)
	}
	if checkType == "uint8" {
		if ptr == nil {
			return uint8(0)
		}
		return ptr.(uint8)
	}
	if checkType == "[]uint8" {
		return this.FromArrayUint8(field)
	}
	if checkType == "int8" {
		if ptr == nil {
			return int8(0)
		}
		return ptr.(int8)
	}
	if checkType == "int16" {
		if ptr == nil {
			return int16(0)
		}
		return ptr.(int16)
	}
	if checkType == "int32" {
		if ptr == nil {
			return int32(0)
		}

		return ptr.(*sql.NullInt32)
	}
	if checkType == "uint32" {
		if ptr == nil {
			return uint32(0)
		}

		return ptr.(uint32)
	}
	if checkType == "uint64" {
		if ptr == nil {
			return uint64(0)
		}
		return ptr.(uint64)
	}
	if checkType == "int64" {
		if ptr == nil {
			return int64(0)
		}
		return ptr.(int64)
	}
	if checkType == "float32" {
		if ptr == nil {
			return float32(0)
		}
		return ptr.(float32)
	}
	if checkType == "float64" {
		if ptr == nil {
			return float64(0)
		}
		return ptr.(float64)
	}
	if checkType == "string" {
		if ptr == nil {
			return ""
		}
		return ptr.(string)
	}

	if checkType == "time.Time" {
		return this.TimeField2Value(field)

	}

	return baseutils.Any2Str(ptr)
}
func (this *IchubRecords) FromArrayUint8(field *IchubField) interface{} {
	ptr := field.Value
	if field.IfFloat() {
		if ptr == nil {
			return float64(0)
		}

		return stringutils.Str2Float64(baseutils.Any2Str(ptr))

	}
	if field.IfInt() {
		if ptr == nil {
			return int64(0)
		}

		return stringutils.Str2Int64(baseutils.Any2Str(ptr))

	}
	if field.GoType == "string" {
		if ptr == nil {
			return ""
		}
		return baseutils.Any2Str(ptr)
	}
	if ptr == nil {
		return new([]uint8)
	}
	return ptr.([]uint8)
}

func (this *IchubRecords) PtrTimeField2Value(field *IchubField) interface{} {
	var ptr = field.Value
	if this.TimeToInt {
		var timevalue = time.Time{}.Unix()
		if ptr == nil {
		}
		timevalue = ptr.(time.Time).Unix()
		return &timevalue
	} else {
		if ptr == nil {
			return &time.Time{}
		}
		return ptr.(*time.Time)
	}

}
func (this *IchubRecords) TimeField2Value(field *IchubField) interface{} {
	var ptr = field.Value
	if this.TimeToInt {
		if ptr == nil {
			return time.Time{}.Unix()
		}
		return ptr.(time.Time).Unix()
	} else {
		if ptr == nil {
			return time.Time{}
		}
		return ptr.(time.Time)
	}

}
func (this *IchubRecords) PtrRow2Result() {

	for _, row := range this.Rows {
		var record = make(map[string]interface{})
		for _, v := range row {
			record[v.Field] = this.PtrField2Value(v)

		}
		this.Records = append(this.Records, record)

	}

}

func (this *IchubRecords) ScanRows(timeToInt bool, sqlRows *sql.Rows) error {
	this.TimeToInt = timeToInt

	for sqlRows.Next() {
		var result, ichubField = this.NewIchubFields2Result()
		var err = sqlRows.Scan(result...)
		if err != nil {
			logrus.Error(err)
			return err
		}
		this.Append(ichubField)
	}
	this.PtrRow2Result()
	this.Count = len(this.Records)
	return nil
}
